package com.google.firebase.quickstart.database.custom.holder;

import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.firebase.quickstart.DemoApplication;
import com.google.firebase.quickstart.database.DemoMessagesActivity;
import com.google.firebase.quickstart.database.R;
import com.google.firebase.quickstart.database.common.data.model.Dialog;
import com.google.firebase.quickstart.database.common.data.model.Message;
import com.google.firebase.quickstart.database.common.data.model.User;
import com.google.firebase.quickstart.database.custom.holder.holders.messages.CustomIncomingImageMessageViewHolder;
import com.google.firebase.quickstart.database.custom.holder.holders.messages.CustomIncomingTextMessageViewHolder;
import com.google.firebase.quickstart.database.custom.holder.holders.messages.CustomOutcomingImageMessageViewHolder;
import com.google.firebase.quickstart.database.custom.holder.holders.messages.CustomOutcomingTextMessageViewHolder;
import com.google.firebase.quickstart.database.utils.AppUtils;
import com.stfalcon.chatkit.messages.MessageHolders;
import com.stfalcon.chatkit.messages.MessageInput;
import com.stfalcon.chatkit.messages.MessagesList;
import com.stfalcon.chatkit.messages.MessagesListAdapter;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CustomHolderMessagesActivity extends DemoMessagesActivity
        implements MessagesListAdapter.OnMessageLongClickListener<Message>,
        MessageInput.InputListener,
        MessageInput.AttachmentsListener {
    public static final String EXTRA_USER = "user";
//    public static final String EXTRA_MESSAGE_KEY = "message_key";
    public static final String EXTRA_DELETETIME_KEY = "deleteTime";
    private User user;
    private DatabaseReference mMessagesReference;
    private DatabaseReference mDatabase;
    public static Map<String, User> userMap = new HashMap<>();
    private String TAG = "CustomHolderMessagesActivity";
    private NotificationManager notificationManager;

    public static void open(Context context) {
        context.startActivity(new Intent(context, CustomHolderMessagesActivity.class));
    }

    private MessagesList messagesList;
    private String messageKey;
    private String messageKey1;
    DatabaseReference chatsReference;
    DatabaseReference databaseReference;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        setContentView(R.layout.activity_custom_holder_messages);
        messagesList = (MessagesList) findViewById(R.id.messagesList);
//        messageKey = (String) getIntent().getStringExtra(EXTRA_MESSAGE_KEY);
        deleteTime = (long) getIntent().getLongExtra(EXTRA_DELETETIME_KEY, 0);
        user = (User) getIntent().getSerializableExtra(EXTRA_USER);
        setTitle(user.getName());
        userMap.put(user.getId(), user);
        userMap.put(DemoApplication.mUser.getId(), DemoApplication.mUser);
        messageKey = DemoApplication.mUser.getId() + "-" + user.getId();
        messageKey1 = user.getId() + "-" + DemoApplication.mUser.getId();
        // Initialize Database
        mDatabase = FirebaseDatabase.getInstance().getReference();
        mMessagesReference = FirebaseDatabase.getInstance().getReference()
                .child("messages").child(messageKey);
        chatsReference = mDatabase.child("chats").child(user.getId()).child(DemoApplication.mUser.getId());
        databaseReference = mDatabase.child("chats").child(DemoApplication.mUser.getId()).child(user.getId());
        databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Dialog dialog = dataSnapshot.getValue(Dialog.class);
                if (dialog != null && dialog.getChatId() != null) {
                    dialog.isChat = true;
                    dialog.unreadCount = 0;
                    Map<String, Object> childUpdates = new HashMap<>();
                    childUpdates.put("/chats/" + DemoApplication.mUser.getId() + "/" + user.getId(), dialog.toMap());
                    mDatabase.updateChildren(childUpdates);
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
        initAdapter();
        MessageInput input = (MessageInput) findViewById(R.id.input);
        input.setInputListener(this);
        input.setAttachmentsListener(this);
    }

    long deleteTime = 0;
    int unReadCount = 0;
    boolean isChat;
    ValueEventListener postListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // Get Post object and use the values to update the UI
            Dialog dialog = dataSnapshot.getValue(Dialog.class);
            if (dialog != null && dialog.getChatId() != null) {
                unReadCount = dialog.unreadCount;
                isChat = dialog.isChat;
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            // Getting Post failed, log a message
            Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
            // ...
        }
    };


    @Override
    public boolean onSubmit(CharSequence input) {
        unReadCount++;
        Message message = new Message(messageKey, DemoApplication.mUser, input.toString());
        Map<String, Object> stringObjectMap = message.toMap();
        mMessagesReference.push().updateChildren(stringObjectMap);
        FirebaseDatabase.getInstance().getReference()
                .child("messages").child(messageKey1).push().updateChildren(stringObjectMap);
//        Map<String, Object> childUpdates = new HashMap<>();
//        Dialog dialog = new Dialog(messageKey, user.getAvatar(), user.getName(), input.toString(), message.getTimestamp(), 0, true);
//        childUpdates.put("/chats/" + DemoApplication.mUser.getId() + "/" + user.getId(), dialog.toMap());
//        Dialog dialog1 = new Dialog(messageKey, DemoApplication.mUser.getAvatar(), DemoApplication.mUser.getName(), input.toString(), message.getTimestamp(), isChat ? 0 : unReadCount, isChat);
//        childUpdates.put("/chats/" + user.getId() + "/" + DemoApplication.mUser.getId(), dialog1.toMap());
//        mDatabase.updateChildren(childUpdates);
//        messagesAdapter.addToStart(message, true);
        postMsg(input);
        return true;
    }

    private void postMsg(final CharSequence input) {
        final Message message = new Message(messageKey, DemoApplication.mUser, input.toString());
        FirebaseDatabase.getInstance().getReference().child("chats").child(DemoApplication.mUser.getId()).child(user.getId())
                .addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        Dialog dialog1 = dataSnapshot.getValue(Dialog.class);
                        Dialog dialog;
                        if (dialog1 != null && dialog1.getChatId() != null) {
                            dialog = new Dialog(messageKey, user.getAvatar(), user.getName(), input.toString(), message.getTimestamp(), 0, true);
                            dialog.deleteTimestamp = dialog1.deleteTimestamp;
                        } else {
                            dialog = new Dialog(messageKey, user.getAvatar(), user.getName(), input.toString(), message.getTimestamp(), 0, true);
                        }
                        Map<String, Object> childUpdates = new HashMap<>();
                        childUpdates.put("/chats/" + DemoApplication.mUser.getId() + "/" + user.getId(), dialog.toMap());
                        mDatabase.updateChildren(childUpdates);
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });
        FirebaseDatabase.getInstance().getReference().child("chats").child(user.getId()).child(DemoApplication.mUser.getId())
                .addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        Dialog dialog1 = dataSnapshot.getValue(Dialog.class);
                        Dialog dialog;
                        if (dialog1 != null && dialog1.getChatId() != null) {
                            dialog = new Dialog(messageKey1, DemoApplication.mUser.getAvatar(), DemoApplication.mUser.getName(), input.toString(), message.getTimestamp(), dialog1.isChat ? 0 : unReadCount, dialog1.isChat);
                            dialog.deleteTimestamp = dialog1.deleteTimestamp;
                        } else {
                            dialog = new Dialog(messageKey1, DemoApplication.mUser.getAvatar(), DemoApplication.mUser.getName(), input.toString(), message.getTimestamp(), isChat ? 0 : unReadCount, isChat);
                        }
                        Map<String, Object> childUpdates = new HashMap<>();
                        childUpdates.put("/chats/" + user.getId() + "/" + DemoApplication.mUser.getId(), dialog.toMap());
                        mDatabase.updateChildren(childUpdates);
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });
    }

    @Override
    public void onAddAttachments() {
//        messagesAdapter.addToStart(MessagesFixtures.getImageMessage(), true);
    }

    @Override
    public void onMessageLongClick(Message message) {
        AppUtils.showToast(this, R.string.on_log_click_message, false);
    }

    private void initAdapter() {
        MessageHolders holdersConfig = new MessageHolders()
                .setIncomingTextConfig(
                        CustomIncomingTextMessageViewHolder.class,
                        R.layout.item_custom_incoming_text_message)
                .setOutcomingTextConfig(
                        CustomOutcomingTextMessageViewHolder.class,
                        R.layout.item_custom_outcoming_text_message)
                .setIncomingImageConfig(
                        CustomIncomingImageMessageViewHolder.class,
                        R.layout.item_custom_incoming_image_message)
                .setOutcomingImageConfig(
                        CustomOutcomingImageMessageViewHolder.class,
                        R.layout.item_custom_outcoming_image_message);

        super.messagesAdapter = new MessagesListAdapter<>(super.senderId, holdersConfig, super.imageLoader);
        super.messagesAdapter.setOnMessageLongClickListener(this);
//        super.messagesAdapter.setLoadMoreListener(this);
        messagesList.setAdapter(super.messagesAdapter);

    }

    ChildEventListener childEventListener;

    @Override
    protected void onStart() {
        super.onStart();
        notificationManager.cancel(0);
        chatsReference.addValueEventListener(postListener);
        messagesAdapter.clear();
        messagesList.setAdapter(super.messagesAdapter);
        // Create child event listener
        // [START child_event_listener_recycler]
        childEventListener = new ChildEventListener() {
            List<Message> messages = new ArrayList<>();
            private List<String> messageIds = new ArrayList<>();

            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
                Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());

                // A new comment has been added, add it to the displayed list
                Message comment = dataSnapshot.getValue(Message.class);

                // [START_EXCLUDE]
                // Update RecyclerView
                messageIds.add(dataSnapshot.getKey());
                messages.add(comment);
                messagesAdapter.addToStart(comment, true);
//                messagesAdapter.notifyItemInserted(messages.size() - 1);
                // [END_EXCLUDE]
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
                Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());

                // A comment has changed, use the key to determine if we are displaying this
                // comment and if so displayed the changed comment.
                Message newComment = dataSnapshot.getValue(Message.class);
                String commentKey = dataSnapshot.getKey();

                // [START_EXCLUDE]
                int commentIndex = messageIds.indexOf(commentKey);
                if (commentIndex > -1) {
                    // Replace with the new data
                    messages.set(commentIndex, newComment);

                    // Update the RecyclerView
                    messagesAdapter.notifyItemChanged(commentIndex);
                } else {
                    Log.w(TAG, "onChildChanged:unknown_child:" + commentKey);
                }
                // [END_EXCLUDE]
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
                Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());

                // A comment has changed, use the key to determine if we are displaying this
                // comment and if so remove it.
                String commentKey = dataSnapshot.getKey();

                // [START_EXCLUDE]
                int commentIndex = messageIds.indexOf(commentKey);
                if (commentIndex > -1) {
                    // Remove data from the list
                    messageIds.remove(commentIndex);
                    messages.remove(commentIndex);

                    // Update the RecyclerView
                    messagesAdapter.notifyItemRemoved(commentIndex);
                } else {
                    Log.w(TAG, "onChildRemoved:unknown_child:" + commentKey);
                }
                // [END_EXCLUDE]
            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
                Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());

                // A comment has changed position, use the key to determine if we are
                // displaying this comment and if so move it.


                // ...
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.w(TAG, "postComments:onCancelled", databaseError.toException());
                Toast.makeText(getApplicationContext(), "Failed to load comments.",
                        Toast.LENGTH_SHORT).show();
            }
        };
        mMessagesReference.orderByChild("timestamp").startAt(deleteTime).addChildEventListener(childEventListener);
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Remove post value event listener
        try {
            databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    Dialog dialog = dataSnapshot.getValue(Dialog.class);
                    if (dialog != null && dialog.getChatId() != null) {
                        dialog.isChat = false;
                        dialog.unreadCount = 0;
                        Map<String, Object> childUpdates = new HashMap<>();
                        childUpdates.put("/chats/" + DemoApplication.mUser.getId() + "/" + user.getId(), dialog.toMap());
                        mDatabase.updateChildren(childUpdates);
                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });
            chatsReference.removeEventListener(postListener);
            mMessagesReference.removeEventListener(childEventListener);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void delete() {
        super.delete();
        mDatabase.child("chats").child(DemoApplication.mUser.getId()).child(user.getId()).child("isDelete").setValue(true);
        mDatabase.child("chats").child(DemoApplication.mUser.getId()).child(user.getId()).child("deleteTimestamp").setValue(new Date().getTime());
        finish();
    }
}
